﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using CkSoftware.GroupMe.Sdk.TestWeb.Helpers;
using CkSoftware.GroupMe.Sdk.TestWeb.Models;

namespace CkSoftware.GroupMe.Sdk.TestWeb.Controllers
{
    public class GroupsController : Controller
    {
		public ActionResult Index()
		{
			var model = new GroupsConfigurationModel
				{
					AuthToken = SessionConfiguration.GetConfigValue<string>(SessionConfiguration.GroupMeClientAuthKey)
				};

			return View(model);
		}

		public ActionResult Configure(GroupsConfigurationModel model)
		{
			if (ModelState.IsValid)
			{
				SessionConfiguration.SetConfigValue(SessionConfiguration.GroupMeClientAuthKey, model.AuthToken);
				return RedirectToAction("List");
			}

			return View("Index", model);
		}

		public async Task<ActionResult> List()
		{
			var groupsListing = await GroupMeHelper.GetGroupsForSessionConfig();
			await groupsListing.FetchAll();

			var model = new GroupsListModel
				{
					Groups = groupsListing.Entries
				};

			return View(model);
		}

		public async Task<ActionResult> FormerList()
		{
			var formerGroups = await GroupMeHelper.GetFormerGroupsForSessionConfig();
			var model = new GroupsListModel
				{
					Groups = formerGroups
				};

			return View(model);
		}

		public async Task<ActionResult> GroupDetail(string groupId)
		{
			var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
			var model = new GroupDetailModel
				{
					GroupId = groupId,
					Data = group
				};

			return View(model);
		}

		public ActionResult Create()
		{
			return View();
		}

		public async Task<ActionResult> CreateGroup(CreateGroupModel model)
		{
			if (ModelState.IsValid)
			{
				var group = await GroupMeHelper.CreateGroup(model);
				return RedirectToAction("GroupDetail", new { groupId = group.Data.Id });
			}

			return View("Create", model);
		}

		public async Task<ActionResult> Update(string groupId)
		{
			var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
			var model = new CreateGroupModel
				{
					GroupName = group.Data.Name,
					Description = group.Data.Description,
					OpenForSharing = !string.IsNullOrEmpty(group.Data.ShareUrl)
				};

			return View(model);
		}

		public async Task<ActionResult> UpdateGroup(string groupId, CreateGroupModel model)
		{
			if (ModelState.IsValid)
			{
				var group = await GroupMeHelper.UpdateGroup(groupId, model);
				return RedirectToAction("GroupDetail", new { groupId = group.Data.Id });
			}

			return View("Update", model);
		}

		public async Task<ActionResult> Delete(string groupId)
		{
			if (!string.IsNullOrEmpty(groupId))
			{
				await GroupMeHelper.DeleteGroup(groupId);
			}

			return RedirectToAction("List");
		}

		public async Task<ActionResult> AddMember(GroupDetailModel model)
		{
			if (ModelState.IsValid)
			{
				var resultData = await GroupMeHelper.AddGroupMember(model.GroupId, model.AddMember);
				return View(new AddedMembersModel {Data = resultData, GroupId = model.GroupId});
			}

			var group = await GroupMeHelper.GetGroupForSessionConfig(model.GroupId);
			model.Data = group;

			return View("GroupDetail", model);
		}

		public async Task<ActionResult> RemoveMember(string groupId, string memberId)
		{
			if (!string.IsNullOrEmpty(groupId) && !string.IsNullOrEmpty(memberId))
			{
				await GroupMeHelper.RemoveMemberFromGroup(groupId, memberId);
			}

			return RedirectToAction("GroupDetail", new {groupId});
		}

		public async Task<ActionResult> GroupMessages(string groupId)
		{
			if (!string.IsNullOrEmpty(groupId))
			{
				var messages = await GroupMeHelper.GetGroupMessagesForSessionConfig(groupId);
				var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
				return View("GroupMessages", new GroupMessagesModel { Group = group.Data, Messages = messages });
			}

			return RedirectToAction("List");
		}

		public async Task<ActionResult> OlderGroupMessages(string groupId)
		{
			if (!string.IsNullOrEmpty(groupId))
			{
				var messages = await GroupMeHelper.LoadOlderMessagesForSessionConfig(groupId);
				var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
				return View("GroupMessages", new GroupMessagesModel { Group = group.Data, Messages = messages });
			}

			return RedirectToAction("List");
		}

		public async Task<ActionResult> CreateGroupMessage(GroupMessagesModel model)
		{
			if (string.IsNullOrEmpty(model.NewMessageText) && string.IsNullOrEmpty(model.NewMessageImageUrl))
			{
				var messages = await GroupMeHelper.GetGroupMessagesForSessionConfig(model.Group.Id);
				var group = await GroupMeHelper.GetGroupForSessionConfig(model.Group.Id);

				model.Group = group.Data;
				model.Messages = messages;
				
				ModelState.AddModelError("NewMessageText", "At least a message must be supplied.");
				return View("GroupMessages", model);
			}

			await GroupMeHelper.CreateNewMessageInGroupForSessionConfig(model.Group.Id, model.NewMessageText, model.NewMessageImageUrl);
			
			return RedirectToAction("GroupMessages", new { groupId = model.Group.Id });
		}

		public async Task<ActionResult> LikeMessage(string groupId, string messageId)
		{
			if (string.IsNullOrEmpty(groupId) || string.IsNullOrEmpty(messageId))
			{
				throw new ArgumentException("The groupId and the messageId must be supplied.");
			}

			await GroupMeHelper.LikeMessageInGroupForSessionConfig(groupId, messageId);

			return RedirectToAction("GroupMessages", new {groupId});
		}

		public async Task<ActionResult> UnlikeMessage(string groupId, string messageId)
		{
			if (string.IsNullOrEmpty(groupId) || string.IsNullOrEmpty(messageId))
			{
				throw new ArgumentException("The groupId and the messageId must be supplied.");
			}

			await GroupMeHelper.UnlikeMessageInGroupForSessionConfig(groupId, messageId);

			return RedirectToAction("GroupMessages", new {groupId});
		}

		public async Task<ActionResult> RefreshMessages(string groupId)
		{
			if (string.IsNullOrEmpty(groupId))
			{
				throw new ArgumentException("The groupId must be supplied.");
			}

			await GroupMeHelper.RefreshGroupMessagesForSessionConfig(groupId);
			
			return RedirectToAction("GroupMessages", new {groupId });
		}

		public async Task<ActionResult> DirectMessages(string memberId, string groupId)
		{
			if (!string.IsNullOrEmpty(memberId))
			{
				var messages = await GroupMeHelper.GetDirectMessagesForSessionConfig(groupId, memberId);
				var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
				return View("DirectMessages", new DirectMessagesModel { Group = group.Data, Member = group.Data.Members.First(m => m.UserId == memberId), Messages = messages });
			}

			return RedirectToAction("List");
		}

		public async Task<ActionResult> OlderDirectMessages(string memberId, string groupId)
		{
			if (!string.IsNullOrEmpty(memberId) && !string.IsNullOrEmpty(groupId))
			{
				var messages = await GroupMeHelper.LoadOlderDirectMessagesForSessionConfig(groupId, memberId);
				var group = await GroupMeHelper.GetGroupForSessionConfig(groupId);
				return View("DirectMessages", new DirectMessagesModel { Group = group.Data, Member = group.Data.Members.First(m => m.UserId == memberId), Messages = messages });
			}

			return RedirectToAction("List");
		}

		public async Task<ActionResult> CreateDirectMessage(DirectMessagesModel model)
		{
			if (string.IsNullOrEmpty(model.NewMessageText) && string.IsNullOrEmpty(model.NewMessageImageUrl))
			{
				var messages = await GroupMeHelper.GetDirectMessagesForSessionConfig(model.Group.Id, model.Member.UserId);
				var group = await GroupMeHelper.GetGroupForSessionConfig(model.Group.Id);

				model.Group = group.Data;
				model.Member = group.Data.Members.First(m => m.UserId == model.Member.UserId);
				model.Messages = messages;
				
				ModelState.AddModelError("NewMessageText", "At least a message must be supplied.");
				return View("DirectMessages", model);
			}

			await GroupMeHelper.CreateNewDirectMessageForSessionConfig(model.Group.Id, model.Member.UserId, model.NewMessageText, model.NewMessageImageUrl);

			return RedirectToAction("DirectMessages", new { groupId = model.Group.Id, memberId = model.Member.UserId });
		}

		public async Task<ActionResult> LikeDirectMessage(string memberId, string groupId, string messageId)
		{
			if (string.IsNullOrEmpty(memberId) || string.IsNullOrEmpty(groupId) || string.IsNullOrEmpty(messageId))
			{
				throw new ArgumentException("The groupId, memberId and the messageId must be supplied.");
			}

			await GroupMeHelper.LikeDirectMessageForSessionConfig(groupId, memberId, messageId);

			return RedirectToAction("DirectMessages", new {groupId, memberId });
		}

		public async Task<ActionResult> UnlikeDirectMessage(string memberId, string groupId, string messageId)
		{
			if (string.IsNullOrEmpty(memberId) || string.IsNullOrEmpty(groupId) || string.IsNullOrEmpty(messageId))
			{
				throw new ArgumentException("The groupId, memberId and the messageId must be supplied.");
			}

			await GroupMeHelper.UnlikeDirectMessageForSessionConfig(groupId, memberId, messageId);

			return RedirectToAction("DirectMessages", new {groupId, memberId });
		}

		public async Task<ActionResult> RefreshDirectMessages(string memberId, string groupId)
		{
			if (string.IsNullOrEmpty(memberId) || string.IsNullOrEmpty(groupId))
			{
				throw new ArgumentException("The groupId and memberId must be supplied.");
			}

			await GroupMeHelper.RefreshDirectMessagesForSessionConfig(groupId, memberId);

			return RedirectToAction("DirectMessages", new {groupId, memberId });
		}
    }
}
